let settings = {
  "examples": [

    {
      "label": "Amsterdam Single Point",
      "geojson": [
        { "type": "Feature", "properties": { "name": "A point in Amsterdam" }, "geometry": { "type": "Point", "coordinates": [4.87793, 52.37560] } }
      ]
    },
    {
      "label": "NYC Single Point",
      "geojson": [
        { "type": "Feature", "properties": { "name": "A point in NYC" }, "geometry": { "type": "Point", "coordinates": [-73.991083, 40.739153] } }
      ]
    },
    {
      "label": "NYC Multiple Point(s) & LineString",
      "geojson": [
        { "type": "Feature", "properties": { "name": "NYC Point A", "icon": "walk" }, "geometry": { "type": "Point", "coordinates": [-73.991083, 40.739153] } }, 
        { "type": "Feature", "properties": { "name": "NYC Point B", "icon": "board" }, "geometry": { "type": "Point", "coordinates": [-73.977623, 40.761723] } }, 
        { "type": "Feature", "properties": { "name": "NYC Point C", "icon": "stop" }, "geometry": { "type": "Point", "coordinates": [-73.986246, 40.738895] } },
        { "type": "Feature", "properties": { "name": "NYC Point D", "icon": "walk" }, "geometry": { "type": "Point", "coordinates": [-73.991457, 40.748817] } }, 
        { "type": "Feature", "properties": null, "geometry": { 
          "type": "LineString", "coordinates": [ 
            [-73.991083, 40.739153], [-73.977623, 40.761723], [-73.986246, 40.738895], [-73.991457, 40.748817] 
          ] } 
        } 
      ]
    }
  ]
};

function parseHashGeoJSON() {
  var hash = window.location.hash.substr(1);
  if (hash) {
    try {
      return {
        "geojson": JSON.parse(decodeURIComponent(hash.replace(/\+/g, " "))),
        "error": null,
      };
    } catch (error) {
      return {
        "geojson": null,
        "error": 'Error parsing GeoJSON from hash: ' + error
      };
    }
  }
  return {
    "geojson": null,
    "error": null,
  };
}

function renderNodataView(errorMessage) {
  let exampleRows = '';
  for (example in settings.examples) {
    let label = settings.examples[example].label;
    let geojsonStr = JSON.stringify(settings.examples[example].geojson);
    let geojsonLink = `#${encodeURI(geojsonStr)}`;
    let row = `
      <tr>
        <td>${label}</td>
        <td><a href="${geojsonLink}">${geojsonStr}</a></td>
      </tr>
    `;
    exampleRows += row
  }

  let errMsg = "";
  if (errorMessage != null) {
    errMsg = `
      <div class='error'>
        <div class='error-message'>${errorMessage}</div>
        <a href="#">Clear error</a>
      </div>
    `;
  }
  document.getElementById("container").innerHTML = `
    <div class='container-inner'>
      <header>
        <h1>GeoJSON Mapview</h1>
        <h4><a href="#">geojson.lrdu.org</a></h4>
      </header>
      <hr></hr>

      ${errMsg}


      <p>
        This is a simple single 1-page Javascript application that
        renders GeoJSON found in the URL (#) hash on a Leaflet Map.
        This can be used to both render groups of Point(s) and routes
        (e.g. connected points) via a LineString.
      </p>

      <p>
        <strong>(1)</strong> Each GeoJSON feature with a 'name' property
        will be automatically be clickable and display the name property
        in an overlay popup.
      </p>

      <p>
        <strong>(2)</strong> If a GeoJSON feature contains a point, and has a
        'icon' property, the icon will be used instead of a generic circle.
        The valid properties for the icon are 'walk', 'board', or 'stop'. See
        the section below for examples.
      </p>

      <p>
        Learn more about GeoJSON: <a target="_blank" href="https://en.wikipedia.org/wiki/GeoJSON">GeoJSON Wikipedia Entry</a>
      </p>

      <hr></hr>

      <h2>Examples:</h2>
      <table>
        <thead>
        <tr><td>Description</td><td>GeoJSON</td></tr>
        </thead>
        ${exampleRows}
      </table>

      <hr></hr>
      
      <footer>
        <p>Licensed in Public Domain by <a href='http://milesalan.com'>Miles Alan<a></p>
      </footer>
    </div>
  `;
}

function renderMapGeojson(geojson) {
  var map = L.map('container').setView([0, 0], 12);

  L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
    attribution: '<a href="#">geojson.lrdu.org</a>'
  }).addTo(map);

  var createIcon = function(path) {
    var iconSize = 20;
    var iconAnchorSize = 10;
    return L.icon({
      iconUrl: path,
      iconSize:     [iconSize, iconSize],
      iconAnchor:   [iconAnchorSize, iconAnchorSize],
      popupAnchor:  [0, -iconAnchorSize]
    });
  }
  var iconWalk = createIcon('appicons/icon_walk.svg');
  var iconBoard = createIcon('appicons/icon_board.svg');
  var iconStop = createIcon('appicons/icon_stop.svg');

  var geojsonLayer = L.geoJSON(geojson, {
    pointToLayer: function (feature, lonlat) {

      var icon = [];
      if ('properties' in feature && 'icon' in feature.properties) {
        if (feature.properties.icon == 'walk') {
          icon = [L.marker(lonlat, { icon: iconWalk })];
        } else if (feature.properties.icon == 'board') {
          icon = [L.marker(lonlat, { icon: iconBoard })];
        } else if (feature.properties.icon == 'stop') {
          icon = [L.marker(lonlat, { icon: iconStop })];
        }
      }
      var circleMarker = L.circleMarker(lonlat, {
        radius: 12,
        fillColor: icon.length == 0 ? 'blue' : "#e8e8e8", 
        color: "#000", 
        weight: 1,
        opacity: 1, 
        fillOpacity: 0.8 
      });

      return L.featureGroup([...icon, circleMarker]);
    },
    onEachFeature: function (feature, layer) {
      if (feature.properties && feature.properties.name) {
        layer.bindPopup(feature.properties.name);
      }
    }
  }).addTo(map);
  map.fitBounds(geojsonLayer.getBounds());
}

window.onload = function() {
  var parseResponse = parseHashGeoJSON();
  if (parseResponse.error != null || parseResponse.geojson == null) {
    renderNodataView(parseResponse.error);
  } else {
    renderMapGeojson(parseResponse.geojson);
  }
};
window.addEventListener('hashchange', function() { window.location.reload(true) });
